MdVerbs.php
<?php
namespace Tlf\Scrawl\Ext;
/**
* Runs `@mdverb` extensions, enabling special callbacks for `@verb()`s in `.src.md` files
*/
class MdVerbs {
protected $regs = [
'verb' =>'/(?<!\\\\)\@([a-zA-Z_]+)\(([^\)]*)\)/m',
];
/** `key=>value` array of verb handlers. value should be callable. key is the verb. */
public $handlers = [];
/**
* Get all `@verbs(arg1, arg2)`
* @return array of verb arrays ... the verb array contains `string src`, `string verb`, and `array args`
*/
public function get_verbs(string $str): array {
$reg = $this->regs['verb'];
preg_match_all($reg, $str, $matches, PREG_SET_ORDER);
$verbs = [];
foreach ($matches as $m){
$verb = [];
$verb['src'] = $m[0];
$verb['verb'] = $m[1];
// `$m[2]` is like `arg1, arg2, arg3`, so i expode on `,` & `trim` with array_map
$verb['args'] =
array_map('trim',
explode(',',$m[2])
);
$verbs[] = $verb;
}
return $verbs;
}
/**
* Get all verbs, execute them, and replace them within the doc
* @param $doc a documentation file's content
*/
public function replace_all_verbs(string $doc): string{
$verbs = $this->get_verbs($doc);
$out = $doc;
foreach ($verbs as $v){
$replacement = $this->run_verb($v['src'], $v['verb'], $v['args']);
$out = str_replace($v['src'], $replacement, $out);
}
return $out;
}
/**
* execute a verb and get its output
* @return string that should replace the `@verb()` call
*/
public function run_verb(string $src, string $verb, array $args): string {
if (!isset($this->handlers[$verb])){
//@todo scrawl->warn()
return '--Verb `@'.$verb.'()` has no handler--';
}
$handler = $this->handlers[$verb];
try {
$ret = $handler(...$args);
} catch (\ArgumentCountError $e){
// @TODO need to use scrawl->warn()
//
echo "\n\nARGUMENT COUNT ERROR ... error reporting incomplete ... see code/Ext/MdVerbs.php";
echo "\n\n";
throw $e;
//
// return '';
// $class = get_class($callable[0]);
// $method = $callable[1];
// echo "\n\n";
// echo "\nCannot call $class->$method() becuase of an argument count error.";
//
// echo "\n\n";
// echo "Error caused by: \n";
// $info = (array)$info;
// $info['file'] = (array)$info['file'];
// $info['file']['content'] = '--content is removed from var dump for readability--';
// print_r($info);
//
// echo "\n\n";
// throw $e;
}
if (!is_string($ret)){
$args_str = implode(', ', $args);
$type = gettype($ret);
throw new \TypeError("Verbs must return strings. @$verb($args_str) returned $type");
}
return $ret;
}
}